package com.blue.core.excel;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.blue.core.util.ReflectionUtil;

/**
 * Excel配置解析器
 *
 * @author zhengjin
 * @since 1.0 2017年12月25日
 */
public class ExcelParser
{
	private static Logger logger = LoggerFactory.getLogger(ExcelParser.class);
	private static ExcelParser instance;

	private Map<Class<?>, ExcelConfig> configMap = new HashMap<>();

	private ExcelParser()
	{
	}

	public static ExcelParser getInstance()
	{
		if (instance == null)
		{
			synchronized (ExcelParser.class)
			{
				if (instance == null)
				{
					instance = new ExcelParser();
				}
			}
		}
		return instance;
	}

	public ExcelConfig parse(Class<?> clazz)
	{
		ExcelConfig config = configMap.get(clazz);
		if (config == null)
		{
			synchronized (this)
			{
				if (config == null)
				{
					Excel anno = clazz.getAnnotation(Excel.class);
					if (anno == null)
						throw new IllegalArgumentException(clazz.getSimpleName() + " 缺少 @Excel 注解");

					config = new ExcelConfig();
					config.setClazz(clazz);
					this.parseColumn(config);
					logger.info("找到 Excel 映射类：{}", clazz.getName());
					configMap.put(clazz, config);
				}
			}
		}
		return config;
	}

	private void parseColumn(ExcelConfig config)
	{
		Map<String, Method> getterMap = ReflectionUtil.getterMap(config.getClazz());
		Map<String, Method> setterMap = ReflectionUtil.setterMap(config.getClazz());
		Map<String, Field> fieldMap = ReflectionUtil.fieldMap(config.getClazz(), false);

		Map<Integer, ExcelColumnConfig> columnMap = new HashMap<>();
		for (Map.Entry<String, Field> entry : fieldMap.entrySet())
		{
			ExcelColumn annoColumn = entry.getValue().getAnnotation(ExcelColumn.class);
			if (annoColumn == null)
				continue;

			Method setter = setterMap.get(entry.getKey());
			Method getter = getterMap.get(entry.getKey());
			if (setter == null || getter == null)
				throw new IllegalArgumentException(String.format("%s 的 %s 字段缺少 setter 方法或 getter 方法",
						config.getClazz().getSimpleName(), entry.getKey()));

			ExcelColumnConfig columnConfig = new ExcelColumnConfig();
			columnConfig.setIndex(annoColumn.columnIndex());
			columnConfig.setName(annoColumn.name());
			columnConfig.setFormat(annoColumn.format());
			columnConfig.setField(entry.getValue());
			columnConfig.setSetter(setter);
			columnConfig.setGetter(getter);

			if (columnMap.containsKey(columnConfig.getIndex()))
				throw new IllegalArgumentException(config.getClazz().getSimpleName() + " 的列索引重复：" + columnConfig.getIndex());

			logger.debug("列 {} 映射字段 {}，类型：{}", annoColumn.columnIndex(), annoColumn.name(), entry.getValue().getType().getName());
			columnMap.put(columnConfig.getIndex(), columnConfig);
		}

		config.setColumnMap(columnMap);
	}

}
